package com.jumi.microservice.api;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jumi.microservice.common.page.TableDataInfo;
import com.jumi.microservice.common.redis.RedisCache;
import com.jumi.microservice.common.utils.ObjectUtils;
import com.jumi.microservice.constant.*;
import com.jumi.microservice.domain.*;
import com.jumi.microservice.mapper.CategoryMapper;
import com.jumi.microservice.mapper.GoodsMapper;
import com.jumi.microservice.mapper.GoodsSkuMapper;
import com.jumi.microservice.mapper.SupplierMapper;
import com.jumi.microservice.service.*;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 商品服务
 *
 * @author Administrator
 */
@RestController
@DubboService
public class CommodityService implements CommodityApi {

    private static final Logger logger = LoggerFactory.getLogger(CommodityService.class);

    /**
     * 商品spu管理service组件
     */
    @Autowired
    private GoodsService goodsService;

    /**
     * 库存管理service组件
     */
    @DubboReference
    private GoodsInventoryApi goodsInventoryApi;

    /**
     * 商品分类管理service组件接口
     */
    @Autowired
    private CategoryService categoryService;

    /**
     * 商品sku管理service组件
     */
    @Autowired
    private GoodsSkuService goodsSkuService;

    /**
     * 商品品牌管理service组件
     */
    @Autowired
    private BrandService brandService;

    /**
     * 商品sku管理mapper组件
     */
    @Autowired
    private GoodsSkuMapper goodsSkuMapper;

    /**
     * 商品管理mapper组件
     */
    @Autowired
    private GoodsMapper goodsMapper;

    /**
     * 商品分类管理mapper组件
     */
    @Autowired
    private CategoryMapper categoryMapper;

    /**
     * 商品供应商管理mapper组件
     */
    @Autowired
    private SupplierMapper supplierMapper;

    @Autowired
    private RedisCache redisCache;

    /**
     * 商品分类名称标识符
     */
    private static final String CATEGORY_IDENTIFIER = ">";

    /**
     * 根据商品名称查询商品spu
     *
     * @param name 商品名称
     * @return 商品Spu
     */
    @Override
    public List<GoodsSpuDTO> getGoodsSpuByName(String name) {
        LambdaQueryWrapper<GoodsDO> goodsWrapper = Wrappers.lambdaQuery();
        goodsWrapper.eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        goodsWrapper.like(!StringUtils.isBlank(name), GoodsDO::getGoodsName, name);
        goodsWrapper.orderByDesc(GoodsDO::getId);
        List<GoodsDO> goodsList = goodsMapper.selectList(goodsWrapper);
        List<GoodsSpuDTO> goodsSpus = new ArrayList<>();
        int enableVirtualNum = redisCache.getCacheObject(GoodsKeyConstant.GOODS_VIRTUALNUM_KEY);
        for (GoodsDO goods : goodsList) {
            GoodsSpuDTO goodsSpu = new GoodsSpuDTO();
            goodsSpu.setGoodsId(goods.getId());
            goodsSpu.setGoodsName(goods.getGoodsName());
            goodsSpu.setCategory(goods.getCreatgroyFirst());

            CategoryDTO category = categoryService.getCategoryById(goodsSpu.getCategory());
            goodsSpu.setCategoryName(category.getCategoryName());
            goodsSpu.setSecondCategory(category.getParentId());
            goodsSpu.setSecondCategoryName(category.getCategoryName() + CATEGORY_IDENTIFIER + category.getParentName());

            goodsSpu.setGoodsPrice(goods.getGoodsPrice());
            goodsSpu.setGoodsMarketprice(goods.getGoodsMarketprice());
            goodsSpu.setGoodsImage(goods.getGoodsImage());
            goodsSpu.setGoodsState(goods.getGoodsState());
            goodsSpu.setSupplyId(goods.getSupplyId());
            goodsSpu.setSupplierCompanyName(goods.getSupplier());

            List<Long> skuIds = goodsService.getSkuIdListBySpuId(goods.getId());
            Integer saleStockQuantity = 0;
            Integer saledStockQuantity = 0;
            if (skuIds.size() > NumberConstant.NUMBER_ZERO.intValue()) {
                List<GoodsSpuInventoryDTO> goodsSpuInventories = goodsInventoryApi.goodsInventoryBySkuIds(skuIds);
                for (GoodsSpuInventoryDTO goodsSpuInventory : goodsSpuInventories) {
                    saleStockQuantity += goodsSpuInventory.getStockQuantity() + goodsSpuInventory.getPreStorage();
                    saledStockQuantity += goodsSpuInventory.getSaledStorage();
                }
            }

            if (enableVirtualNum == NumberConstant.NUMBER_ONE.intValue()) {
                Integer virtualNum = goodsSkuService.countVirtualNumBySpuId(goods.getId());
                saledStockQuantity += virtualNum;
            }

            goodsSpu.setSaleStockQuantity(saleStockQuantity);
            goodsSpu.setSaledStockQuantity(saledStockQuantity);
            goodsSpus.add(goodsSpu);
        }
        return goodsSpus;
    }

    /**
     * 根据商品名称分页查询商品spu(活动模块)
     *
     * @param goodsSearchQuery 商品查询实体
     * @return 商品Spu
     */
    @Override
    public TableDataInfo<GoodsSpuDTO> getGoodsSpuByNameAndPage(GoodsSearchQuery goodsSearchQuery) {
        TableDataInfo<GoodsSpuDTO> tableDataInfo = new TableDataInfo<>();
        List<GoodsSpuDTO> goodsSpus = new ArrayList<>();

        LambdaQueryWrapper<GoodsDO> goodsWrapper = Wrappers.lambdaQuery();
        goodsWrapper.eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        goodsWrapper.eq(goodsSearchQuery.getSupplyId() != null, GoodsDO::getSupplyId, goodsSearchQuery.getSupplyId());
        goodsWrapper.eq(goodsSearchQuery.getCategoryId() != null, GoodsDO::getCreatgroySecond, goodsSearchQuery.getCategoryId());
        goodsWrapper.like(!StringUtils.isBlank(goodsSearchQuery.getKeyWord()), GoodsDO::getGoodsName, goodsSearchQuery.getKeyWord());
        //添加活动 过滤已经添加过活动的spuid
        goodsWrapper.notIn(CollectionUtil.isNotEmpty(goodsSearchQuery.getSpuIds()), GoodsDO::getId, goodsSearchQuery.getSpuIds());
        goodsWrapper.orderByDesc(GoodsDO::getId);

        IPage<GoodsDO> goodsDoPage = new Page<>(goodsSearchQuery.getPageNum(), goodsSearchQuery.getPageSize());
        goodsDoPage = goodsMapper.selectPage(goodsDoPage, goodsWrapper);

        int enableVirtualNum = redisCache.getCacheObject(GoodsKeyConstant.GOODS_VIRTUALNUM_KEY);

        for (GoodsDO goods : goodsDoPage.getRecords()) {
            GoodsSpuDTO goodsSpu = new GoodsSpuDTO();
            goodsSpu.setGoodsId(goods.getId());
            goodsSpu.setGoodsName(goods.getGoodsName());
            goodsSpu.setCategory(goods.getCreatgroyFirst());

            CategoryDTO category = categoryService.getCategoryById(goodsSpu.getCategory());
            goodsSpu.setCategoryName(category.getCategoryName());

            goodsSpu.setSecondCategory(goods.getCreatgroySecond());
            String secondCreatgroyName = categoryService.getCategoryById(goods.getCreatgroySecond()).getCategoryName();
            goodsSpu.setSecondCategoryName(category.getCategoryName() + CATEGORY_IDENTIFIER + secondCreatgroyName);

            goodsSpu.setGoodsPrice(goods.getGoodsPrice());
            goodsSpu.setGoodsMarketprice(goods.getGoodsMarketprice());
            goodsSpu.setGoodsImage(goods.getGoodsImage());
            goodsSpu.setGoodsState(goods.getGoodsState());
            goodsSpu.setSupplyId(goods.getSupplyId());
            goodsSpu.setSupplierCompanyName(goods.getSupplier());

            List<Long> skuIds = goodsService.getSkuIdListBySpuId(goods.getId());
            Integer saleStockQuantity = 0;
            Integer saledStockQuantity = 0;
            if (skuIds.size() > NumberConstant.NUMBER_ZERO.intValue()) {
                List<GoodsSpuInventoryDTO> goodsSpuInventories = goodsInventoryApi.goodsInventoryBySkuIds(skuIds);
                for (GoodsSpuInventoryDTO goodsSpuInventory : goodsSpuInventories) {
                    saleStockQuantity += goodsSpuInventory.getStockQuantity() + goodsSpuInventory.getPreStorage();
                    saledStockQuantity += goodsSpuInventory.getSaledStorage();
                }
            }

            if (enableVirtualNum == NumberConstant.NUMBER_ONE.intValue()) {
                Integer virtualNum = goodsSkuService.countVirtualNumBySpuId(goods.getId());
                saledStockQuantity += virtualNum;
                saleStockQuantity += virtualNum;
            }

            goodsSpu.setSaleStockQuantity(saleStockQuantity);
            goodsSpu.setSaledStockQuantity(saledStockQuantity);
            goodsSpus.add(goodsSpu);
        }
        tableDataInfo.setTotal(goodsDoPage.getTotal());
        tableDataInfo.setRows(goodsSpus);
        return tableDataInfo;
    }

    /**
     * 根据spuid集合查询商品
     *
     * @param goodsIds 商品spuid集合
     * @return 商品
     */
    @Override
    public List<GoodsSpuDTO> getGoodsSpuByIds(List<Long> goodsIds, Boolean isFront, Long uid) {
        List<GoodsSpuDTO> goodsSpuList = new ArrayList<>();
        for (Long spuId : goodsIds) {
            GoodsSpuDTO goodsSpu = new GoodsSpuDTO();
            GoodsDTO goods = goodsService.getGoodsById(spuId);
            goodsSpu.setGoodsId(goods.getId());
            goodsSpu.setGoodsName(goods.getGoodsName());
            goodsSpu.setGoodsDescription(goods.getGoodsDescription());
            goodsSpu.setCategory(goods.getCreatgroyFirst());
            CategoryDTO category = categoryService.getCategoryById(goodsSpu.getCategory());
            goodsSpu.setCategoryName(category.getCategoryName());
            goodsSpu.setSecondCategory(category.getParentId());
            goodsSpu.setSecondCategoryName(category.getCategoryName() + CATEGORY_IDENTIFIER + category.getParentName());

            if (isFront) {
                Object cacheObject = redisCache.getCacheObject(GoodsKeyConstant.POSTAGEGOODS + goods.getId());
                if (!Objects.isNull(cacheObject)) {
                    if (Objects.nonNull(uid)) {
                        goodsSpu.setGoodsPrice(goods.getGoodsPrice());
                    } else {
                        goodsSpu.setGoodsPrice(BigDecimal.ZERO);
                    }
                } else {
                    goodsSpu.setGoodsPrice(goods.getGoodsPrice());
                }
            } else {
                goodsSpu.setGoodsPrice(goods.getGoodsPrice());
            }
            goodsSpu.setGoodsMarketprice(goods.getGoodsMarketprice());
            goodsSpu.setGoodsImage(goods.getGoodsImage());
            goodsSpu.setGoodsState(goods.getGoodsState());

            BrandDO brand = brandService.getById(goods.getBrandId());
            if (brand != null) {
                goodsSpu.setBrandName(brand.getBrandName());
            }

            List<Long> skuIds = goodsService.getSkuIdListBySpuId(spuId);
            if (CollectionUtil.isNotEmpty(skuIds)) {
                List<GoodsSpuInventoryDTO> goodsSpuInventories = goodsInventoryApi.goodsInventoryBySkuIds(skuIds);
                int saleStockQuantity = 0;
                int saledStockQuantity = 0;
                for (GoodsSpuInventoryDTO goodsSpuInventory : goodsSpuInventories) {
                    if (goodsSpuInventory.getStockQuantity() != null) {
                        saleStockQuantity += goodsSpuInventory.getStockQuantity() + goodsSpuInventory.getPreStorage();
                    }

                    if (goodsSpuInventory.getSaledStorage() != null) {
                        saledStockQuantity += goodsSpuInventory.getSaledStorage();
                    }
                }
                goodsSpu.setSaleStockQuantity(saleStockQuantity);
                goodsSpu.setSaledStockQuantity(saledStockQuantity);
                goodsSpuList.add(goodsSpu);
            }
        }
        return goodsSpuList;
    }

    /**
     * 根据spuid集合查询该spu ID，图片，名称，重量/个
     *
     * @param name 商品spuid名称
     * @return 该spu ID，图片，名称，重量/个
     */
    @Override
    public List<GoodsInfoDTO> getGoodsByName(String name) {
        GoodsSearchQuery goodsSearchQuery = new GoodsSearchQuery();
        goodsSearchQuery.setKeyWord(name);
        List<GoodsDTO> goodsList = goodsService.searchGoodsByPage(goodsSearchQuery, false);

        List<GoodsInfoDTO> goodsSpus = new ArrayList<>();
        for (GoodsDTO goods : goodsList) {
            GoodsInfoDTO goodsSpu = new GoodsInfoDTO();
            goodsSpu.setId(goods.getId());
            goodsSpu.setGoodsType(goods.getGoodsType());
            goodsSpu.setGoodsName(goods.getGoodsName());
            goodsSpu.setGoodsImage(goods.getGoodsImage());

            LambdaQueryWrapper<GoodsSkuDO> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(GoodsSkuDO::getGoodsId, goods.getId());
            List<GoodsSkuDO> goodsSkus = goodsSkuMapper.selectList(wrapper);

            if (goodsSkus != null) {
                goodsSkus.sort((x, y) -> Double.compare(x.getWeight().doubleValue(), y.getWeight().doubleValue()));
                if (goodsSkus.size() == NumberConstant.NUMBER_ONE.intValue()) {
                    goodsSpu.setWeight(goodsSkus.get(NumberConstant.NUMBER_ZERO.intValue()).getWeight());
                } else if (goodsSkus.size() > NumberConstant.NUMBER_ONE.intValue()) {
                    goodsSpu.setWeight(goodsSkus.get(goodsSkus.size() - NumberConstant.NUMBER_ONE.intValue()).getWeight());
                }
            }

            String firstCreatgroyName =
                    categoryService.getCategoryById(goods.getCreatgroyFirst()).getCategoryName();
            String secondCreatgroyName =
                    categoryService.getCategoryById(goods.getCreatgroySecond()).getCategoryName();
            goodsSpu.setCategoryName(firstCreatgroyName + CATEGORY_IDENTIFIER + secondCreatgroyName);
            goodsSpu.setBrandName(brandService.selectById(goods.getBrandId()).getBrandName());

            Integer goodsState = goods.getGoodsState();
            if (goodsState.equals(GoodsStatus.PUTTED_ON_SHELVES.getCode())) {
                goodsSpu.setGoodsState(GoodsStatus.PUTTED_ON_SHELVES.getDesc());
            } else if (goodsState.equals(GoodsStatus.PULLED_OFF_SHELVES.getCode())) {
                goodsSpu.setGoodsState(GoodsStatus.PULLED_OFF_SHELVES.getDesc());
            } else if (goodsState.equals(GoodsStatus.FIX_PUTTED_ON_SHELVES.getCode())) {
                goodsSpu.setGoodsState(GoodsStatus.FIX_PUTTED_ON_SHELVES.getDesc());
            } else {
                goodsSpu.setGoodsState(GoodsStatus.UNKNOWN.getDesc());
            }
            goodsSpus.add(goodsSpu);
        }
        return goodsSpus;
    }

    /**
     * 根据skuid集合查询该skuID的图片,名称(退货模块)
     *
     * @param skuIds 商品skuid集合
     * @return 该skuID，图片,名称
     */
    @Override
    public List<GoodsSkuInfoDTO> getGoodsSkuInfoByIds(List<Long> skuIds) {
        List<GoodsSkuInfoDTO> goodsSkuList = new ArrayList<>();
        List<GoodsSkuDTO> goodsSkus = goodsSkuService.listGoodsSkuByIds(skuIds);
        for (GoodsSkuDTO goodsSkuDto : goodsSkus) {
            GoodsSkuInfoDTO goodsSku = new GoodsSkuInfoDTO();
            goodsSku.setId(goodsSkuDto.getId());
            goodsSku.setGoodsId(goodsSkuDto.getGoodsId());
            goodsSku.setGoodsImage(goodsSkuDto.getGoodsPropertyImage());
            goodsSku.setGoodsName(goodsSkuDto.getGoodsName());

            GoodsDO goodsDO = goodsMapper.selectById(goodsSkuDto.getGoodsId());
            String returnAddress = goodsDO.getReturnAddress();
            if (!StringUtils.isBlank(returnAddress)) {
                String[] returnAddressArray = returnAddress.split(" ");
                if (returnAddressArray.length == NumberConstant.NUMBER_THREE.intValue()) {
                    goodsSku.setAddressee(returnAddressArray[NumberConstant.NUMBER_ZERO.intValue()]);
                    goodsSku.setMobile(returnAddressArray[NumberConstant.NUMBER_ONE.intValue()]);
                    goodsSku.setReturnAddress(returnAddressArray[NumberConstant.NUMBER_TWO.intValue()]);
                } else {
                    goodsSku.setAddressee(StringUtils.EMPTY);
                    goodsSku.setMobile(StringUtils.EMPTY);
                    goodsSku.setReturnAddress(StringUtils.EMPTY);
                }
            }else {
                goodsSku.setAddressee(StringUtils.EMPTY);
                goodsSku.setMobile(StringUtils.EMPTY);
                goodsSku.setReturnAddress(StringUtils.EMPTY);
            }
            goodsSkuList.add(goodsSku);
        }
        return goodsSkuList;
    }

    /**
     * 根据sku名称模糊查询该skuID
     *
     * @param name 商品sku名称
     * @return 该skuID map集合
     */
    @Override
    public Map<Long, String> getGoodsSkuIdByName(String name) {
        Map<Long, String> skuMap = new HashMap<>();

        LambdaQueryWrapper<GoodsSkuDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(GoodsSkuDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        wrapper.like(StringUtils.isNotEmpty(name), GoodsSkuDO::getGoodsName, name);
        List<GoodsSkuDO> goodsSkus = goodsSkuMapper.selectList(wrapper);
        for (GoodsSkuDO goodsSku : goodsSkus) {
            skuMap.put(goodsSku.getId(), goodsSku.getGoodsName());
        }
        return skuMap;
    }

    /**
     * 根据spuid集合查询商品 优选
     *
     * @param goodsIds 商品spuid集合
     * @return 商品
     */
    @Override
    public GoodsgetOptimizationDTO getOptimizationGoodsBySpuIds(List<Long> goodsIds) {
        //获取商品信息
        List<GoodsDTO> dtos = goodsService.goodsListBySpuId(goodsIds);
        if (CollectionUtil.isEmpty(dtos)) {
            return new GoodsgetOptimizationDTO();
        }
        //获取所有的品牌信息
        List<BrandDO> brands = brandService.list(
                Wrappers.<BrandDO>lambdaQuery()
                        .eq(BrandDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .eq(BrandDO::getStatus, StatusEnum.STATUS_YES.getCode()));
        List<Long> skuids = dtos.stream().map(spu -> {return spu.getId();}).collect(Collectors.toList());
        //获取库存信息
        List<GoodsSpuInventoryDTO> stockDtos = goodsInventoryApi.goodsInventoryBySpuId4Activity(goodsIds);
//        List<GoodsSpuStockDTO> stocks = stockDto.getSpuStocks();

        List<GoodsVirtualDTO> goodsVirtuals = null;
        // 判断是否开启虚拟销量
        int enableVirtualNum = redisCache.getCacheObject(GoodsKeyConstant.GOODS_VIRTUALNUM_KEY);
        if(NumberConstant.NUMBER_ONE.intValue()==enableVirtualNum){
            goodsVirtuals = goodsSkuMapper.selectGoodsVirtualNum(skuids);
        }

        List<GoodsVirtualDTO> finalGoodsVirtuals = goodsVirtuals;
        return new GoodsgetOptimizationDTO(dtos.stream().map(dto -> {
            GoodsgetOptimizationGoodsBySpuIdsDTO spu = new GoodsgetOptimizationGoodsBySpuIdsDTO();
            spu.setId(dto.getId());
            spu.setGoodsImage(dto.getGoodsImage());
            spu.setGoodsMarketprice(dto.getGoodsMarketprice() != null ? dto.getGoodsMarketprice().setScale(NumberConstant.NUMBER_TWO.intValue()).toString() : "0.00");
            spu.setGoodsName(dto.getGoodsName());
            spu.setGoodsPrice(dto.getGoodsPrice() != null ? dto.getGoodsPrice().setScale(NumberConstant.NUMBER_TWO.intValue()).toString() : "0.00");
            spu.setSpuCode(dto.getSpuCode());
            GoodsSpuInventoryDTO sp = stockDtos.stream().filter(s -> dto.getId().equals(s.getSpuId())).findAny().orElse(null);
            if (sp != null) {
                spu.setStockNum(sp.getStockQuantity());
                spu.setSaledNum(sp.getSaledStorage());
            }
            //品牌名称
            BrandDO brand = brands.stream().filter(b -> dto.getBrandId().equals(b.getId())).findAny().orElse(null);
            if (brand != null) {
                spu.setBrandName(brand.getBrandName());
            }
            //分类
            spu.setCreatgroyFirst(dto.getCreatgroyFirst());
            //销量 : 实际销量+虚拟销量
            if(CollectionUtil.isNotEmpty(finalGoodsVirtuals)){
                GoodsVirtualDTO goodsVirtualDTO = finalGoodsVirtuals.stream().filter(godv->godv.getSpuId().equals(dto.getId())).findAny().orElse(null);
                if (goodsVirtualDTO!=null){
                    spu.setSaledNum(spu.getSaledNum()+goodsVirtualDTO.getVirtualNum());
                }
            }
            return spu;
        }).collect(Collectors.toList()));
    }

    /**
     * 根据分类id获取商品信息 优选
     *
     * @param categoryId 分类id
     * @return
     */
    @Override
    public ActivityGoodsCategoryDTO goodsByCategory4Activity(Long categoryId) {
        //先获取所有的一级分类信息
        List<CategoryDTO> categorys = categoryService.listCategoryById(null);
        List<GoodsCategoryDTO> categores = categorys.stream().map(ca -> {
            GoodsCategoryDTO dto = new GoodsCategoryDTO();
            dto.setCategoryId(ca.getId());
            dto.setCategoryName(ca.getCategoryName());
            return dto;
        }).collect(Collectors.toList());
        //获取分类下的所有的商品id 活动中有商品的分类id
//        List<Long> spuIds = null;
//        if(categoryId!=null) {
//            List<Object> ids = goodsMapper.selectObjs(
//                    Wrappers.<GoodsDO>lambdaQuery()
//                            .eq(GoodsDO::getCreatgroyFirst, categoryId));
//            spuIds = (List<Long>) (List) ids;
//        }
        return new ActivityGoodsCategoryDTO(null, categores);
    }

    /**
     * 查询商品的二级分类
     *
     * @return 商品的二级分类集合
     */
    @Override
    public List<CategoryDTO> listCategory() {
        LambdaQueryWrapper<CategoryDO> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(CategoryDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        wrapper.eq(CategoryDO::getStatus, StatusEnum.STATUS_YES.getCode());
        wrapper.isNotNull(CategoryDO::getParentId);

        List<CategoryDO> categories = categoryMapper.selectList(wrapper);
        List<CategoryDTO> categoryDtos = convertCategoryDoList2DtoList(categories);

        categoryDtos.stream().filter(categoryDto -> categoryDto.getParentId() != null)
                .forEach(categoryDto -> {
                    CategoryDO category = categoryMapper.selectById(categoryDto.getParentId());
                    categoryDto.setCategoryName(category.getCategoryName() + CATEGORY_IDENTIFIER + categoryDto.getCategoryName());
                    categoryDto.setParentName(category.getCategoryName());
                });
        return categoryDtos;
    }

    /**
     * 根据供应商名称模糊查询商品的供应商集合
     *
     * @param name 供应商名称
     * @return 商品的供应商集合
     */
    @Override
    public List<SupplierDTO> listSupplier(String name) {
        QueryWrapper<SupplierDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT supply_id,supplier_company_name,status,is_del").orderByAsc("supply_id")
                .lambda()
                .like(StringUtils.isNotBlank(name), SupplierDO::getSupplierCompanyName, name)
                .eq(SupplierDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                .eq(SupplierDO::getStatus, StatusEnum.STATUS_YES.getCode());

        List<SupplierDO> suppliers = supplierMapper.selectList(queryWrapper);
        return convertSupplierDoList2DtoList(suppliers);
    }

    /**
     * 热销排行榜商品列表
     *
     * @return 热销排行榜商品列表
     */
    @Override
    public List<HostSaleGoodsDTO> listHostSaleGoods(Integer topN) {
        List<HostSaleGoodsDTO> hostSaleGoodsList = new ArrayList<>();
        LambdaQueryWrapper<GoodsDO> goodsWrapper = Wrappers.lambdaQuery();
        goodsWrapper.eq(GoodsDO::getIsDel, StatusEnum.STATUS_NO.getCode());
        goodsWrapper.eq(GoodsDO::getGoodsState, GoodsStatus.PUTTED_ON_SHELVES.getCode());

        List<GoodsDO> goodsList = goodsMapper.selectList(goodsWrapper);
        List<Long> spuIds = new ArrayList<>();
        goodsList.forEach(goods -> spuIds.add(goods.getId()));
        Map<Long, Integer> saledStorageMap = goodsInventoryApi.getSaledStorageBySpuIds(spuIds);

        QueryWrapper<GoodsSkuDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("goods_id ,sum(virtual_num) virtualNum")
                .eq(" is_del", 0)
                .groupBy("goods_id")
                .in("goods_id", spuIds)
                .having("sum(virtual_num) > 0");
        List<GoodsSkuDO> objectList = goodsSkuMapper.selectList(queryWrapper);
        Map<Long, Integer> spuVirtualNumMap = objectList.stream().collect(Collectors.toMap(GoodsSkuDO::getGoodsId, GoodsSkuDO::getVirtualNum));

        // 判断是否开启虚拟销量
        int enableVirtualNum = redisCache.getCacheObject(GoodsKeyConstant.GOODS_VIRTUALNUM_KEY);
        for (GoodsDO goodsDo : goodsList) {
            HostSaleGoodsDTO hostSaleGoods = new HostSaleGoodsDTO();
            hostSaleGoods.setGoodsId(goodsDo.getId());
            hostSaleGoods.setGoodsName(goodsDo.getGoodsName());
            hostSaleGoods.setGoodsImage(goodsDo.getGoodsImage());
            hostSaleGoods.setGoodsPrice(goodsDo.getGoodsPrice());
            hostSaleGoods.setGoodsMarketprice(goodsDo.getGoodsMarketprice());
            if (saledStorageMap.containsKey(goodsDo.getId())) {
                hostSaleGoods.setSaledStockQuantity(saledStorageMap.get(goodsDo.getId()));
            } else {
                hostSaleGoods.setSaledStockQuantity(NumberConstant.NUMBER_ZERO.intValue());
            }

            if (enableVirtualNum == NumberConstant.NUMBER_ONE.intValue()) {
                if (spuVirtualNumMap.containsKey(goodsDo.getId())) {
                    Integer virtualNum = spuVirtualNumMap.get(goodsDo.getId());
                    hostSaleGoods.setSaledStockQuantity(hostSaleGoods.getSaledStockQuantity() + virtualNum);
                }
            }
            hostSaleGoodsList.add(hostSaleGoods);
        }

        //按销量降序排序
        hostSaleGoodsList.sort((x, y) -> -Integer.compare(x.getSaledStockQuantity(), y.getSaledStockQuantity()));
        return hostSaleGoodsList.stream().filter(item -> item.getSaledStockQuantity() > 0).limit(topN).collect(Collectors.toList());
    }

    /**
     * 根据spuid集合查询商品(付邮领获取非下架商品)
     *
     * @param goodsIds 商品spuid集合
     * @return 商品
     */
    @Override
    public GoodsPostageActivityDTO getNoDownGoodsBySpuIds(List<Long> goodsIds, Long page, Long size) {
        logger.info("付邮领获取商品信息传输spuid顺序: {}", JSONObject.toJSONString(goodsIds));
        List<GoodsSpuDTO> goodsSpuList = new ArrayList<>();
        List<BigInteger> newSpuids = (List<BigInteger>) (List) goodsIds;
        List<Long> spuIds = new ArrayList<>();
        QueryWrapper qw = new QueryWrapper();
        qw.eq("goods_state", StatusEnum.STATUS_YES.getCode());
        qw.in("id", goodsIds);
        qw.orderBy(true, true, "field(id," + newSpuids.stream().map(String::valueOf).collect(Collectors.joining(",")) + ")");
        IPage<GoodsDO> pageInfo = goodsMapper.selectPage(new Page<>(page, size), qw);
        pageInfo.getRecords().stream().forEach(goo -> {
            spuIds.add(goo.getId());
            GoodsSpuDTO goodsSpu = new GoodsSpuDTO();
            goodsSpu.setGoodsId(goo.getId());
            goodsSpu.setGoodsName(goo.getGoodsName());
            goodsSpu.setGoodsDescription(goo.getGoodsDescription());
            goodsSpu.setCategory(goo.getCreatgroyFirst());
            CategoryDTO category = categoryService.getCategoryById(goodsSpu.getCategory());
            goodsSpu.setCategoryName(category.getCategoryName());
            goodsSpu.setSecondCategory(category.getParentId());
            goodsSpu.setSecondCategoryName(category.getCategoryName() + CATEGORY_IDENTIFIER + category.getParentName());
            goodsSpu.setGoodsPrice(goo.getGoodsPrice());
            goodsSpu.setGoodsMarketprice(goo.getGoodsMarketprice());
            goodsSpu.setGoodsImage(goo.getGoodsImage());
            goodsSpu.setGoodsState(goo.getGoodsState());
            Object cacheObject = redisCache.getCacheObject(GoodsKeyConstant.POSTAGEGOODS + goo.getId());
            if (!Objects.isNull(cacheObject)) {
                goodsSpu.setGoodsPrice(BigDecimal.ZERO);
            } else {
                goodsSpu.setGoodsPrice(goo.getGoodsPrice());
            }
            List<Long> skuIds = goodsService.getSkuIdListBySpuId(goo.getId());
            if (CollectionUtil.isNotEmpty(skuIds)) {
                List<GoodsSpuInventoryDTO> goodsSpuInventories = goodsInventoryApi.goodsInventoryBySkuIds(skuIds);
                int saleStockQuantity = 0;
                int saledStockQuantity = 0;
                for (GoodsSpuInventoryDTO goodsSpuInventory : goodsSpuInventories) {
                    if (goodsSpuInventory.getStockQuantity() != null) {
                        saleStockQuantity += goodsSpuInventory.getStockQuantity() + goodsSpuInventory.getPreStorage();
                    }
                    if (goodsSpuInventory.getSaledStorage() != null) {
                        saledStockQuantity += goodsSpuInventory.getSaledStorage();
                    }
                }
                goodsSpu.setSaleStockQuantity(saleStockQuantity);
                goodsSpu.setSaledStockQuantity(saledStockQuantity);
                goodsSpuList.add(goodsSpu);
            }
        });
        return new GoodsPostageActivityDTO(goodsSpuList, spuIds, pageInfo.getTotal());
    }

    /**
     * 获取所有的隐私商品的skuid
     *
     * @return
     */
    @Override
    public List<Long> getPrivacyGoodsSkuIds() {
        QueryWrapper<GoodsSkuDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id");
        queryWrapper.apply("goods_id in ( select id from commodity_goods where is_privacy = 1)");
        List<Object> skuIds = goodsSkuMapper.selectObjs(queryWrapper);
        if (CollectionUtil.isNotEmpty(skuIds)) {
            return (List<Long>) (List) skuIds;
        }
        return new ArrayList<>();
    }

    /**
     * 获取所有的隐私商品的spuID
     *
     * @return
     */
    @Override
    public List<Long> getPrivacyGoodsSPuIds() {
        QueryWrapper<GoodsDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id");
        queryWrapper.eq("is_privacy", NumberConstant.NUMBER_ONE);
        List<Object> spuIds = goodsMapper.selectObjs(queryWrapper);
        if (CollectionUtil.isNotEmpty(spuIds)) {
            return (List<Long>) (List) spuIds;
        }
        return new ArrayList<>();
    }

    /**
     * 根据spuid获取商品信息(活动 包含虚拟销量)
     * @param goodsIds 商品spuid
     * @return
     */
    @Override
    public GoodsActivityDTO getGoodsSpuByIds4Activity(List<Long> goodsIds) {
        GoodsActivityDTO goodsActivityDTO = new GoodsActivityDTO();
        List<GoodsSpuDTO> goodsSpuList = new ArrayList<>();
        //判断是否开启了虚拟销量
        int enableVirtualNum = redisCache.getCacheObject(GoodsKeyConstant.GOODS_VIRTUALNUM_KEY);
        //如果开启了虚拟销量 返回商品的虚拟销量
        if(NumberConstant.NUMBER_ONE.intValue()==enableVirtualNum){
            List<GoodsVirtualDTO> goodsVirtuals = goodsSkuMapper.selectGoodsVirtualNum(goodsIds);
            goodsActivityDTO.setGoodsVirtuals(goodsVirtuals);
        }
        //调用库存服务 获取spu销量
        List<GoodsSpuInventoryDTO> goodsSpuInventoryDTOS = goodsInventoryApi.goodsInventoryBySpuId4Activity(goodsIds);
        //先查出所有的商品信息 后遍历取
        List<GoodsDO> allGoods = goodsMapper.selectList(
                Wrappers.<GoodsDO>lambdaQuery()
                        .in(GoodsDO::getId, goodsIds));
        for (GoodsDO goods : allGoods) {
            GoodsSpuDTO goodsSpu = new GoodsSpuDTO();
            goodsSpu.setGoodsId(goods.getId());
            goodsSpu.setGoodsName(goods.getGoodsName());
            goodsSpu.setGoodsDescription(goods.getGoodsDescription());
            goodsSpu.setCategory(goods.getCreatgroyFirst());
//            CategoryDTO category = categoryService.getCategoryById(goodsSpu.getCategory());
//            goodsSpu.setCategoryName(category.getCategoryName());
//            goodsSpu.setSecondCategory(category.getParentId());
//            goodsSpu.setSecondCategoryName(category.getCategoryName() + CATEGORY_IDENTIFIER + category.getParentName());

            Object cacheObject = redisCache.getCacheObject(GoodsKeyConstant.POSTAGEGOODS + goods.getId());
            if (!Objects.isNull(cacheObject)) {
                goodsSpu.setGoodsPrice(BigDecimal.ZERO);
            } else {
                goodsSpu.setGoodsPrice(goods.getGoodsPrice());
            }
            goodsSpu.setGoodsMarketprice(goods.getGoodsMarketprice());
            goodsSpu.setGoodsImage(goods.getGoodsImage());
            goodsSpu.setGoodsState(goods.getGoodsState());
            BrandDO brand = brandService.getById(goods.getBrandId());
            if (brand != null) {
                goodsSpu.setBrandName(brand.getBrandName());
            }
            int saleStockQuantity = 0;
            int saledStockQuantity = 0;
            if (CollectionUtil.isNotEmpty(goodsSpuInventoryDTOS)) {
                GoodsSpuInventoryDTO goodsSpuInventory = goodsSpuInventoryDTOS.stream().filter(spu->spu.getSpuId().equals(goods.getId())).findAny().orElse(null);
                if(goodsSpuInventory!=null){
                    if (goodsSpuInventory.getStockQuantity() != null) {
                        saleStockQuantity += goodsSpuInventory.getStockQuantity() + goodsSpuInventory.getPreStorage();
                    }

                    if (goodsSpuInventory.getSaledStorage() != null) {
                        saledStockQuantity += goodsSpuInventory.getSaledStorage();
                    }
                }
            }
            goodsSpu.setSaleStockQuantity(saleStockQuantity);
            goodsSpu.setSaledStockQuantity(saledStockQuantity);
            goodsSpuList.add(goodsSpu);
        }
        goodsActivityDTO.setGoodsSpus(goodsSpuList);
        return goodsActivityDTO;
    }

    @Override
    public Map<Integer,String> getGoodsSkuThirdPartyCode(List<Integer> skuId) {
        Map<Integer, String> spuVirtualNumMap = null;
        if(null != skuId){
            QueryWrapper<GoodsSkuDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("id ,sku_third_party_code")
                    .in("id", skuId)
                    .eq(" is_del", 0)
                    .orderByDesc("id");
            List<GoodsSkuDO> objectList = goodsSkuMapper.selectList(queryWrapper);
            spuVirtualNumMap = objectList.stream().collect(Collectors.toMap(g->g.getId().intValue(), GoodsSkuDO::getSkuThirdPartyCode));
        }
        return spuVirtualNumMap;
    }


    /**
     * 获取商品spu短名称
     * @param spuId spuid集合
     * @return
     */
    @Override
    public List<GoodsShortNameInfoDTO> getGoodsShortNameInfo4Order(List<Long> spuId) {
        List<GoodsDO> goods = goodsMapper.selectList(
                Wrappers.<GoodsDO>lambdaQuery()
                        .in(GoodsDO::getId, spuId));
        return goods.stream().map(good->{
            GoodsShortNameInfoDTO goodsShortNameInfo = new GoodsShortNameInfoDTO();
            goodsShortNameInfo.setSpuId(good.getId());
            goodsShortNameInfo.setShortName(good.getShortName());
            return goodsShortNameInfo;}).collect(Collectors.toList());
    }

    /**
     * 获取品牌分页信息
     * @param bid 已存在的品牌id
     * @param name 搜索名称
     * @param current 分页
     * @param size 分页
     * @return
     */
    @Override
    public ActivityGoodsBrandPageDTO getGoodsBrandInfo4Activity(List<Long> bid, String name, Long current, Long size) {
        ActivityGoodsBrandPageDTO activityGoodsBrandPageDTO = new ActivityGoodsBrandPageDTO();
        Page<BrandDO> page = brandService.page(
                new Page<>(current, size),
                Wrappers.<BrandDO>lambdaQuery()
                        .eq(BrandDO::getStatus, StatusEnum.STATUS_YES.getCode())
                        .eq(BrandDO::getIsDel, StatusEnum.STATUS_NO.getCode())
                        .like(StrUtil.isNotEmpty(name), BrandDO::getBrandName, name)
                        .notIn(CollectionUtil.isNotEmpty(bid), BrandDO::getId, bid)
                        .orderByDesc(BrandDO::getOrderNum, BrandDO::getCreateTime));
        List<ActivityGoodsBrandDTO> brands = page.getRecords().stream().map(br->{
            ActivityGoodsBrandDTO  activityGoodsBrandDTO = new ActivityGoodsBrandDTO();
            activityGoodsBrandDTO.setId(br.getId());
            activityGoodsBrandDTO.setOrderNum(br.getOrderNum());
            activityGoodsBrandDTO.setBrandName(br.getBrandName());
            activityGoodsBrandDTO.setLogo(br.getLogo());
            activityGoodsBrandDTO.setBrandSlogan(br.getBrandSlogan());
            return activityGoodsBrandDTO;
        }).collect(Collectors.toList());
        activityGoodsBrandPageDTO.setBrands(brands);
        activityGoodsBrandPageDTO.setTotal(page.getTotal());
        return activityGoodsBrandPageDTO;
    }

    /**
     * 将商品分类DO对象集合转换为DTO对象集合
     *
     * @param categories 商品分类DO集合
     * @return List<CategoryDTO> 商品分类DTO对象集合
     */
    private List<CategoryDTO> convertCategoryDoList2DtoList(List<CategoryDO> categories) {
        List<CategoryDTO> categoryDtoList = null;
        try {
            categoryDtoList = ObjectUtils.convertList(categories, CategoryDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return categoryDtoList;
    }

    /**
     * 将商品sku供应商 DO对象转换为DTO对象
     *
     * @param supplier 商品sku供应商 DO
     * @return GoodsDTO 商品sku供应商 DTO
     */
    private List<SupplierDTO> convertSupplierDoList2DtoList(List<SupplierDO> supplier) {
        List<SupplierDTO> supplierDtoList = null;
        try {
            supplierDtoList = ObjectUtils.convertList(supplier, SupplierDTO.class);
        } catch (Exception e) {
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return supplierDtoList;
    }
}
